"""
Author: runyu.ma

meta_pystr_pass.py
"""

from typing import Dict
from ..core.dslc_parser import String, Identifier, Number, BlockOp, BinaryOp
from ..core.dslc_symbol_table import SymbolTable


def meta_pystr_in_node(stab: SymbolTable, top: String):
    if not isinstance(top, String):
        raise ValueError("not String Node")
    if top.strong:
        return top
    #TODO: 如果就在BinaryOp，不需要这里给一个赋值，相关功能要在meta_pystr实现
    param = stab.lsvisiable()
    #print(stab, param)
    if not top.parent or isinstance(top.parent, BlockOp):
        raise ValueError("meta need wrap in Op, not bare String")
    #macro定义时也会出现字符串，这时的eval会失败；TODO:判断是不是macro定义中的字符串
    try:
        if not top.strong:
            ret = __eval_pystr(param, top)
            if isinstance(ret, str):
                ret = "\""+ret+"\""
        else:
            ret = top.value
    except Exception as e:
        print("META corrupt:", e, top.value.format_map(param))
        ret = top.value
    #meta用来更新symbol table
    pop = top.parent
    if isinstance(pop, BinaryOp) and pop.op == '=':
        if isinstance(pop.l, Identifier):
            isym = stab.lookup(pop.l.name)
            if isym:
                isym.info['ival'] = ret#"\'"+ret+"\'"
            else:
                stab.add(pop.l.name, {'ival': ret})#"\'"+ret+"\'"})
    #保持一个引号在外面，下次eval的时候依然出来的是一个string
    #TODO:思考一下这里，eval出来应该就是具体的量了，print不对应该修改print逻辑
    #TODO:print逻辑，所有的量都是str,并且用""包裹，比如'print(%d)'%5变成'print(%s)'%"5"
    rettop = String(ret)#String("\'"+ret+"\'")
    rettop.parent = top.parent
    return rettop


def __eval_pystr(param: Dict[str, str], top: String):
    print('__eval_pystr', top, param)
    ret = eval(top.value.format_map(param))
    return ret

